	/** Create a ByteBuffer from a byte array
	 *  
	 * 
	*byte[] bytes = new byte[10];
	*ByteBuffer buf = ByteBuffer.wrap(bytes);
	
	*Retrieve bytes between the position and limit
	* (see Putting Bytes into a ByteBuffer)
	*bytes = new byte[buf.remaining()];
	*buf.get(bytes, 0, bytes.length);

	* Retrieve all bytes in the buffer
	*buf.clear();
	*bytes = new byte[buf.capacity()];
	*buf.get(bytes, 0, bytes.length);
	 */
/**
 * This class uses the received packet and translates each byte into the headers and data.
 * IPV4 Length = 20bytes
 * Total length = IPV4Length + UDP or TCPHeader Length + Data [exclude ethernet header length]
 */

import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;


import jpcap.NetworkInterface;
import jpcap.packet.ARPPacket;
import jpcap.packet.EthernetPacket;
import jpcap.packet.ICMPPacket;
import jpcap.packet.IPPacket;
import jpcap.packet.Packet;
import jpcap.packet.TCPPacket;
import jpcap.packet.UDPPacket;


public class Packet_Builder extends Packet {
	//All variables are set to default values***************
	//Misc**************************************************
	private utils util = new utils();
	
	//Frame Types*******************************************
	/** PUP protocol */
	public final short ETHERTYPE_PUP = 0x0200;
	/** IP protocol */
	public final short ETHERTYPE_IP  = 0x0800;
	/** Addr. resolution protocol */
	public final short ETHERTYPE_ARP = 0x0806;  
	/** reverse Addr. resolution protocol */
	public final short ETHERTYPE_REVARP = (short)0x8035;
	/** IEEE 802.1Q VLAN tagging */
	public final short ETHERTYPE_VLAN = (short)0x8100;
	/** IPv6 */
	public final short ETHERTYPE_IPV6 = (short)0x86dd;  
	/** used to test interfaces */
	public final short ETHERTYPE_LOOPBACK = (short)0x9000;  
	
	//Ethernet Header***************************************
	/** Source Mac Address number */
	public byte[] src_Mac = new byte[6];
	/** Destination Mac Address number */
	public byte[] dst_Mac = new byte[6];
	/** Frame type default Ethertype_ip*/
	public short frametype = ETHERTYPE_IP;
	
	//TCP/IP HEADER*****************************************
	/** Source port number */
	public int src_port = 12;
	/** Destination port number */
	public int dst_port = 34;
	/** Sequence number */
	public long sequence = 56;
	public byte[] sequence_byte = new byte[4];
	/** ACK number */
	public long ack_num = 78;
	public byte[] acknowledge_byte = new byte[4];
	/** URG flag */
	public boolean urg = false;
	/** ACK flag */
	public boolean ack = false;
	/** PSH flag */
	public boolean psh = false;
	/** RST flag */
	public boolean rst = false;
	/** SYN flag */
	public boolean syn = true;
	/** FIN flag */
	public boolean fin = true;
       /** RSV1 flag */        
	public boolean rsv1 = true;
        /** RSV2 flag */        
	public boolean rsv2 = true;
	/** Window size */
	public int window = 10;
	/** Urgent pointer */
	public short urgent_pointer = 0;
	/**Header length*/
	public byte header_len;
	/**Checksum */
	public int checksum_tcp;
	//UDP/IP HEADER*****************************************
	/**Length*/
	public int udp_Length;
	public int checksum_udp;
	//Internet Protocol version 4****************************
	/** IP version (v4/v6) */
	public byte version;
	/** Priority (class) (v4/v6) */
	public byte priority = 0;
	/** IP flag bit: [D]elay (v4) */
	public boolean d_flag = false;
	/** IP flag bit: [T]hrough (v4) */
	public boolean t_flag = false;
	/** IP flag bit: [R]eliability (v4) */
	public boolean r_flag = false;
	/** Type of Service (TOS) (v4/v6) */
	public byte rsv_tos = 0;
	/** Packet length (v4/v6) */
	public short length;
	/** Fragmentation reservation flag (v4) */
	public boolean rsv_frag = false;
	/** Don't fragment flag (v4) */
	public boolean dont_frag = true;
	/** More fragment flag (v4) */
	public boolean more_frag = false;
	/** Fragment offset (v4) */
	public short offset = 0;
	/** Hop Limit, Time To Live (TTL) (v4/v6) */
	public short hop_limit = 128;
	/** Protocol (v4/v6) */
	public short protocol;
	/**Checksum */
	public int checksum_ipv4;
	//Protocol numbers***************************************
	/** Protocol number for ICMP */
	public static final short IPPROTO_ICMP = 1;
	/** Protocol number for IGMP */
	public static final short IPPROTO_IGMP = 2;
	/** Protocol number for IP in IP */
	public static final short IPPROTO_IP = 4;
	/** Protocol number for TCP */
	public static final short IPPROTO_TCP = 6;
	/** Protocol number for UDP */
	public static final short IPPROTO_UDP = 17;
	/** Protocol number for IPv6 */
	public static final short IPPROTO_IPv6 = 41;
	/** Protocol number for IPv6 hop-by-hop option */
	public static final short IPPROTO_HOPOPT = 0;
	/** Protocol number for routing header for IPv6 */
	public static final short IPPROTO_IPv6_Route = 43;
	/** Protocol number for fragment header for IPv6 */
	public static final short IPPROTO_IPv6_Frag = 44;
	/** Protocol number for IPv6 ICMP */
	public static final short IPPROTO_IPv6_ICMP = 58;
	/** Protocol number for no next header header for IPv6 */
	public static final short IPPROTO_IPv6_NoNxt = 59;
	/** Protocol number for destination option for IPv6 */
	public static final short IPPROTO_IPv6_Opts = 60;

	/** IDENTIFICATION (v4) */
	public int ident = 1010101;
	/** Flow label (v6) */
	public int flow_label;
	/** Source IP address */
	public InetAddress src_ip = InetAddress.getByName("192.168.1.100");
	/** Destination IP address */
	public InetAddress dst_ip = InetAddress.getByName("192.168.1.101");
	/** Option in IPv4 header (v4) */
	public byte[] option;
	
	//Address Resolution Protocol (ARP)	
	/** Hardware type */
	public short hardtype = HARDTYPE_ETHER;
	/** Hardware type: Ethernet */
	public static final short HARDTYPE_ETHER=1;
	/** Hardware type: Token ring */
	public static final short HARDTYPE_IEEE802=6;
	/** Hardware type: Frame relay */
	public static final short HARDTYPE_FRAMERELAY=15;

	/** Protocol type */
	public short prototype;
	/** Protocol type: IP  Protocol 0x800 = 2048*/
	public short PROTOTYPE_IP=2048;

	/** Hardware address length */
	public short hlen = 6;

	/** Protocol address length */
	public short plen = 4;

	/** Operation */
	public short operation = 1;
	/** ARP request */
	public static final short ARP_REQUEST=1;
	/** ARP reply */
	public static final short ARP_REPLY=2;
	/** Reverse ARP request */
	public static final short RARP_REQUEST=3;
	/** Reverse ARP reply */
	public static final short RARP_REPLY=4;
	/** Identify peer request */
	public static final short INV_REQUEST=8;
	/** Identify peer response */
	public static final short INV_REPLY=9;


	/** Sender hardware address */
	public byte[] sender_hardaddr = new byte[6];
	/** Sender protocol address */
	public byte[] sender_protoaddr = new byte[4];;
	/** Target hardware address */
	public byte[] target_hardaddr = new byte[6];;
	/** Target protocol address */
	public byte[] target_protoaddr = new byte[4];;

	//END INTERNET HEADER VARIABLES ***************************
	//DATA VARIABLE********************************************
	/**Header Packet*/
	public byte[] header;
	/**Data packet*/
	public byte[] data_v = ("dat").getBytes();
	
	private int packet_offset_data_size;
	public Packet pkt;
	public EthernetPacket ep;	
	//END DATA VARIABLES***************************************
	
	public Packet_Builder(Packet pkt) throws UnknownHostException
	{
			this.pkt = pkt;
	}
	
	public void initCapturedValues() throws UnknownHostException
	{				
		ep = (EthernetPacket)pkt.datalink;
		ByteBuffer bb_header = ByteBuffer.allocate(pkt.header.length+20);
		bb_header.put(pkt.header);
		bb_header.rewind();
																											/**Ethernet Header*/
		bb_header.get(src_Mac, 0, 6);																		//Source Mac
		bb_header.get(dst_Mac, 0, 6);																		//Destination Mac
		frametype = bb_header.getShort();																	//Frame Type		
		if(ep.frametype==2048)
		{																										
																											/**IPV4 Header*/
			if(bb_header.get()==69)version = 4;																//Version
			rsv_tos = bb_header.get();																		//TOS
			length = bb_header.getShort();																	//Total Length
			ident = bb_header.getShort()  & 0xffff;															//Identification
			if(bb_header.get()==40)	dont_frag = true;	else	more_frag = true;							//Fragmentation
			offset = (short) (bb_header.get() & 0xff);														//Fragment offset
			hop_limit = (short) (bb_header.get() & 0xff);													//TTL
			protocol = (short) (bb_header.get() & 0xff);													//Protocol type
			checksum_ipv4 = bb_header.getShort() & 0xffff;													//IPV4 Checksum
			src_ip = InetAddress.getByAddress(readPartialByteBuffer(bb_header,0,4));						//Source IP Address
			dst_ip = InetAddress.getByAddress(readPartialByteBuffer(bb_header,0,4));						//Destination IP Address
			src_port = bb_header.getShort() & 0xffff;														//Source Port
			dst_port = bb_header.getShort() & 0xffff;														//Destination Port
			if(protocol==6)
			{
				 																							/**TCP Header*/				
				sequence = bb_header.getInt() & 0xffffffffL;												//Sequence Number [bb_header.get(sequence_byte, 0, 4); sequence = byteToInt(sequence_byte);]
				ack_num = bb_header.getInt()  & 0xffffffffL;												//Acknowledgment Number
				header_len = bb_header.get();																//Header Length
				int flag_data = bb_header.get();															//Flag	
				urg = (flag_data == 32) ? true : false; flag_data = (urg==true)?flag_data-32:flag_data-0;	//Urg Flag
				ack = (flag_data >= 16) ? true : false; flag_data = (ack==true)?flag_data-16:flag_data-0;	//Ack Flag
				psh = (flag_data >= 8) ? true : false;  flag_data = (psh==true)?flag_data- 8:flag_data-0;	//Psh Flag
				rst = (flag_data >= 4) ? true : false;  flag_data = (rst==true)?flag_data- 4:flag_data-0;	//Rst Flag
				syn = (flag_data >= 2) ? true : false;  flag_data = (syn==true)?flag_data- 2:flag_data-0;	//Syn Flag
				fin = (flag_data >= 1) ? true : false;  flag_data = (fin==true)?flag_data- 1:flag_data-0;	//Fin Flag
				window = bb_header.getShort() & 0xffff;														//Window Size
				checksum_tcp = bb_header.getShort() & 0xffff;												//TCP Checksum
			}else
			{																								/**TCP Header*/
				udp_Length = bb_header.getShort() & 0xffff;													//UDP Length
				checksum_udp = bb_header.getShort() & 0xffff;												//UDP Checksum
			}			
		}
		if(ep.frametype==2054)
		{																									/**Address Resolution Protocol(ARP)*/
			hardtype = bb_header.getShort();																//Hardware Type
			PROTOTYPE_IP = bb_header.getShort();															//Protocol Type
			hlen = bb_header.get();																			//Hardware Size
			plen = bb_header.get();																			//Protocol Size
			operation = bb_header.getShort();																//Operation Code (Opcode)
			bb_header.get(sender_hardaddr, 0, 6);															//Sender MAC Address
			bb_header.get(sender_protoaddr, 0, 4);															//Sender IP Address
			bb_header.get(target_hardaddr, 0, 6);															//target MAC Address
			bb_header.get(target_protoaddr, 0, 4);															//target IP Address
		}
		packet_offset_data_size = (more_frag==true)?pkt.data.length: 0;
	}
	/**
	 * Creates TCP PAcket
	 * @param src_port
	 * @param dst_port
	 * @param dstIP
	 * @return
	 */
	public TCPPacket createTCPPacket(int src_port,int dst_port,String srcIP,String dstIP,boolean urg_f, boolean ack_f, boolean psh_f,boolean rst_f,boolean syn_f, boolean fin_f
			,long seq,long ack)
	{		
		window = 4096;
		urgent_pointer = 0;
		rsv1 = false; rsv2 = false;
		TCPPacket tcp = new TCPPacket(src_port,dst_port,seq,ack,urg_f,ack_f,psh_f,rst_f,syn_f,fin_f,rsv1,rsv2,window,urgent_pointer);		
		try {
			priority = 0;
			d_flag = false;	t_flag = false;	r_flag = false;
			rsv_tos = 0; 
			rsv_frag = false; dont_frag = true; more_frag = false;
			if(more_frag)
			{
				offset = (short) (packet_offset_data_size/8);
			}
			hop_limit = 128;
			tcp.setIPv4Parameter(priority,d_flag,t_flag,r_flag,rsv_tos,rsv_frag,dont_frag,more_frag,offset,(ident++),
					hop_limit,IPPROTO_TCP,InetAddress.getByName(srcIP),InetAddress.getByName(dstIP));
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
		tcp.data = data_v;
		return tcp;
	}
	/**
	 * Creates an ARP Packet to send
	 * @param sender_mac
	 * @param sender_ipaddress
	 * @param target_mac
	 * @param target_ipaddress
	 * @return
	 */
	public ARPPacket createARPPacket(byte[] sender_mac, byte[] sender_ipaddress, byte[] target_mac, byte[] target_ipaddress,short hardtype, short opcode)
	{
		ARPPacket ap = new ARPPacket();
		ap.hardtype = hardtype;
		ap.prototype = PROTOTYPE_IP;
		ap.hlen = 6;
		ap.plen = 4;
		ap.operation = opcode;
		ap.sender_hardaddr = sender_mac;
		ap.sender_protoaddr = sender_ipaddress;
		ap.target_hardaddr = target_mac;
		ap.target_protoaddr = target_ipaddress;
		return ap;
	}
	/**
	 * Create UDP Packet
	 * UDP Length = UDPHeader + DATA
	 * @param src_port
	 * @param dst_port
	 * @return
	 */
	public UDPPacket createUDPPacket(int src_port,int dst_port,String srcIP, String dstIP)
	{
		UDPPacket udp = new UDPPacket(src_port,dst_port);
		try {			
			priority = 0;
			d_flag = false;	t_flag = false;	r_flag = false;
			rsv_tos = 0; 
			rsv_frag = false; dont_frag = true; more_frag = false;
			offset = (more_frag)?(short) (packet_offset_data_size/8):0; 	
						
			hop_limit = 128;
			udp.setIPv4Parameter(priority,d_flag,t_flag,r_flag,rsv_tos,rsv_frag,dont_frag,more_frag,offset,
					(ident++),hop_limit,IPPROTO_UDP,InetAddress.getByName(srcIP),InetAddress.getByName(dstIP));
			udp.data = data_v;
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return udp;
	}
	/**
	 * Create an ICMP Packet [Ping]
	 * @param srcIP
	 * @param dstIP
	 * @param type
	 * @param code
	 * @return
	 */
	public ICMPPacket createICMPPacket(String srcIP, String dstIP,byte type, byte code)
	{
		ICMPPacket icmp = new ICMPPacket();
		try {
		priority = 0;
		d_flag = false;	t_flag = false;	r_flag = false;
		rsv_tos = 0; 
		rsv_frag = false; dont_frag = false; more_frag = false;
		offset = (more_frag)?(short) (packet_offset_data_size/8):0; 					
		hop_limit = 64;
		if(type==8) ident = randomIDENGenerator();		
			icmp.setIPv4Parameter(priority,d_flag,t_flag,r_flag,rsv_tos,rsv_frag,dont_frag,more_frag,offset,
					ident,hop_limit,IPPROTO_UDP,InetAddress.getByName(srcIP),InetAddress.getByName(dstIP));
			icmp.type = type;
			icmp.code = code;
			if(type==8){
				icmp.id = randomIDENGenerator();
				icmp.seq = 7;
			}else icmp.id = 0;
			icmp.data = ("dsadfdjiopfsdsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").getBytes();
			
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
		return icmp;
	}
	/**
	 * Generates a random Identification 
	 * @return
	 */
	short randomIDENGenerator(){
		return (short)(Math.random() * (65535 - 0) + 0);
	}

	/**
	 * returns a byte buffer of a new length
	 * @param bb
	 * @param offset
	 * @param length
	 * @return
	 */
	public byte[] readPartialByteBuffer(ByteBuffer bb,int offset,int length)
	{
		byte[] bytes = new byte[length];
		bb.get(bytes,offset,length);
		return bytes;
	}
	
	public void setPkt(Packet pkt) throws UnknownHostException {
		this.pkt = pkt;
		initCapturedValues();		
	}
		
}
